Skip to main content link. Accesskey S
  • Help
  • HCL Logo
  • HCL Sametime wiki
  • THIS WIKI IS READ-ONLY. Individual names altered for privacy purposes.
  • HCL forums and blogs
  • Home
  • Product Documentation
  • Community Articles
  • Learning Center
Search
Community Articles > Sametime Standard > Sametime Standard best practices > Integrating Java desktop applications with IBM Sametime using the Sametime Proxy Server
  • Share Show Menu▼
  • Subscribe Show Menu▼

Recent articles by this author

Integrating Java desktop applications with IBM Sametime using the Sametime Proxy Server

The IBM Sametime Proxy Server offers a powerful integration platform. This article demonstrates how to leverage it to integrate a Java desktop application with IBM Sametime.
Community articleIntegrating Java desktop applications with IBM Sametime using the Sametime Proxy Server
Added by ~Olga Chulupulettu | Edited by ~Denise Ekresaplopoden on November 1, 2012 | Version 7
  • Actions Show Menu▼
expanded Abstract
collapsed Abstract
The IBM Sametime Proxy Server offers a powerful integration platform. This article demonstrates how to leverage it to integrate a Java desktop application with IBM Sametime.
ShowTable of Contents
HideTable of Contents
  • 1 What is the IBM Sametime Proxy Server?
  • 2 Integrating with the Sametime Proxy Server
    • 2.1 The asynchronous update problem
    • 2.2 Comet and the long poll
  • 3 Setting up the development environment
  • 4 Managing the Proxy Server long-poll connection
    • 4.1 Logging in and establishing the long poll
    • 4.2 Terminating the long poll and logging out
  • 5 Making changes and receiving updates
    • 5.1 Changing the user presence status & status message
    • 5.2 Receiving status update from other users
  • 6 Conclusion
  • 7 Resources
  • 8 About the author

What is the IBM Sametime Proxy Server?


Introduced with IBM® Sametime® version 8.5, the Sametime Proxy Server is a Web-based application server allowing applications to securely integrate with IBM Sametime and benefit from its real-time collaborative features, using a simple HTTP-based Representational State Transfer (REST) API and the JavaScript Object Notation (JSON) data format.

The main integration targets are rich Internet applications written in JavaTMScript, but thanks to its powerful and language-agnostic REST API, the Sametime Proxy Server can be used to provide real-time collaborative capabilities to any applications.
In this article, we specifically demonstrate how it can be used to integrate IBM Sametime with Java desktop applications. To get the most from the article, you should have a general understanding of HTTP and the REST architecture, and a feature-level knowledge of IBM Sametime.

Sametime Proxy Server is part of the Sametime Standard offering and runs on top of IBM WebSphere® Application Server. Like all other components of the Sametime infrastructure, it can (but doesn't need to) be administered using the Sametime System Console. To run the Sametime Proxy server, you must have a pre-installed Sametime Community Server (see figure 1).

Figure 1. Sametime Proxy and Community Servers



Integrating with the Sametime Proxy Server


The Sametime Proxy Server offers a rich, powerful, and secure REST API, which is documented in the Sametime Software Developer Kit (SDK). Like all REST APIs, it is used by making an HTTP request to the appropriate URI on the server and passing the relevant parameters.

The sample code attached to this article shows how this can be done. One specific technical point, however, deserves a little more explanation before we go into the nitty-gritty details of the code.

The asynchronous update problem


HTTP is essentially a disconnected, request – response protocol, in which a client (like a browser) makes a request for a resource and receives it to present to the user. IBM Sametime, on the user hand, is a real-time collaborative system in which random updates can arrive at any time (think of a user in your contact list changing his status from “Available” to “In a meeting”).

Because the client doesn't know when an update will be available, it cannot make a request to retrieve it, and the server doesn't have any other way to send it to the client.

Comet and the long poll


To work around this issue, the Sametime Proxy Server uses a technique known as “Comet”, in which a separate, long-held HTTP request is made to the server by the client to receive an asynchronous update. We refer to this separate request as the “long poll”.

The long poll is initiated by the client (see figure 2). Until an asynchronous update arrives, the server keeps the long-poll connection open (hence its name). When an asynchronous notification arrives, the server uses the opened long-poll connection to send it to the client. The client receives the notification and re-starts a new long-poll connection.

If no asynchronous updates have arrived after a certain time (about 30 seconds), the long poll is terminated by the server with no response, and the client must restart it.

Figure 2. Long poll in action



The Proxy Server uses JSON as a data format, and the long poll is no exception; the updates received by the long poll are JSON data packets. For reference, JSON is a lightweight, text-based, data interchange format.

Remember, the long poll is an additional connection and is not used by the client to send requests to the server, only to receive asynchronous updates. The client can create additional “standard” HTTP requests to the server to retrieve resources and make REST APIs calls.

Setting up the development environment


Now that we understand the concepts, we can get started with the code writing. For the purpose of integrating desktop Java applications with the Sametime Proxy Server, we need the following:
  • A Java development environment; we use Eclipse 4.1 available from Eclipse.org.
  • A HTTP client Java library; we use the Apache HttpComponents HttpClient 4.1
  • A JSON processing Java library; we use json-simple 1.1.1

Follow these steps to import the code provided with this article into the Eclipse development environment:

attached .zip file and unzip them on the workstation.
2. Start Eclipse and select Window --- Preferences from the menu, to open the Preferences window.
3. Navigate to the Java --- Build Path --- User Libraries Preference window and click the New button, to create a new user library.
4. Type “JSON-SIMPLE” for the library name, and click OK
5. Now Click the Add JARs button, and select the json-simple.1.1.1.jar file unzipped in Step 1 from the json-simple package.
6. Repeat steps 4 and 5 to create another user library named “APACHE_HTTPCOMPONENTS” and containing the following JARs from the Apache HttpComponents package unzipped in Step 1:

  • commons-codec-1.4.jar
  • commons-logging.1.1.1.jar
  • httpclient-4.1.3.jar
  • httpcore-4.1.4.jar

7. The Preferences window should now look like that in figure 3. Click OK to close it.

Figure 3. User Libraries Preferences window



8. Select File --- Import, to open the Import window.
9. In the tree view, select General --- Existing Projects into Workspace, and click Next.
10. Select the Select archive file field and browse for the .zip file containing the sample code for this article downloaded in Step 2; click Finish.

You now have the sample project STProxyClient opened in your Eclipse development environment.

Managing the Proxy Server long-poll connection


In this section we show how a Java application can log into the Sametime Proxy Server and handle the long-poll connection to receive asynchronous updates.

All the REST APIs used in this section are documented in the “Browser Client Toolkit Guide” of the Sametime SDK.

Logging in and establishing the long poll


The first thing the application must do is log in to the Sametime Proxy Server, using the Login REST API, Its URI is stwebapi/user/connect, its method POST, and it accepts the parameters listed in table 1.

Table 1. Login REST API parameters

 

    Name
    Type
    Description
    username
    String
    The user login name
    password
    String
    The user password
    loginMethod
    String
    The type of login (by password, by token, etc ...)
    initialstatus
    Integer
    The initial presence status (available, away, etc ...)
    intitialmsg
    String
    The initial presence message

To log in, we create an HTTP POST request, set the parameters, and execute it (see listing 1). The response contains a JSON object and, if the request is successful, the object contains a value named sessionid, which is the unique ID assigned by the Proxy Server to this user's session. We will need it to establish the long poll, so we extract it from the JSON response.

Listing 1. The login() method of the SametimeProxyClient class


	 public JSONObject login(String userName, String password, Integer initialStatus, String initalMessage) throws IOException, SametimeProxyClientException {

	 

	 // The list of parameters for the REST API call

	 

	 List<NameValuePair> params = new ArrayList<NameValuePair>();

	 params.add(new BasicNameValuePair(LOGIN_LOGIN_METHOD_PARAM, LoginMethod.BY_PASSWORD.getMethod()));

	 if (userName == null)

	 throw new NullPointerException();

	 params.add(new BasicNameValuePair(LOGIN_USERNAME_PARAM, userName)); // The user name

	 if (password == null)

	 throw new NullPointerException();

	 params.add(new BasicNameValuePair(LOGIN_PASSWORD_PARAM, password)); // The password

	 if (initialStatus != null)

	 params.add(new BasicNameValuePair(LOGIN_INITIALSTATUS_PARAM, String.valueOf(initialStatus)));

	 if (initalMessage != null)

	 params.add(new BasicNameValuePair(LOGIN_INITIALMESSAGE_PARAM, initalMessage));

	 UrlEncodedFormEntity entity = new UrlEncodedFormEntity(params, "UTF-8");

	 

	 // This REST call requires a HTTP POST 

	 

	 HttpPost method = new HttpPost(LOGIN_REQUEST_URI); // URI is /user/connect

	 method.setEntity(entity);

	 

	 // Making the HTTP request and retrieving the Session ID from the response

	 

	 JSONObject json = executeProxyRestMethodAndRelease(method);

	 String sessionId = (String) json.get(USER_CONNECT_SESSION_ID_JSON_FIELD);

	 

	 // Starting the long poll handler

	 

	 m_longPollHandler.start(this, sessionId, userName);

	 

	 return json;

	 }

	 

Next, our application must establish (and manage) the long poll. This is achieved in our sample code by the ProxyLongPollHandler class.

Once the application has successfully logged in and retrieved the user session ID, it starts the long poll by making a HTTP PUT request to the /stwebapi/RTCServlet//user (where is replaced by the session ID obtained from the log-in) with a “userName” parameter containing the logged-in user name (see listing 2).

If the request is successful, it returns a JSON object containing a unique value known as the rtc4web nonce. This will be used in subsequent long-poll requests to link them to this specific user session. To that end, we save it in the m_nonce field.

Listing 2. Initiating the long poll

	 public void start(ProxyLongPollListener listener, String sessionIdentifier, String userName) throws IOException, SametimeProxyClientException {

	 

	 int status = 0;

	 HttpEntity entity = null;

	 Reader jsonResponse = null;

	 HttpResponse response = null;

	 

	 

	 if (m_sessionId != null)

	 throw new SametimeProxyClientException("Long poll handler already started");

	 

	 m_listener = listener;

	 

	 // Creating the long poll initiation HTTP request

	 

	 List<NameValuePair> params = new ArrayList<NameValuePair>();

	 params.add(new BasicNameValuePair(USER_NAME_PARAMETER, userName));

	 

	 try {

	 String uriString = MessageFormat.format(LONG_POLL_INIT_REQUEST_URI, new Object[] { sessionIdentifier });

	 

	 URI uri = URIUtils.createURI(null, null, -1, uriString, URLEncodedUtils.format(params, "UTF-8"), null);

	 HttpPut method = new HttpPut(uri); 

	 

	 // Executing the long poll initiation HTTP request

	 

	 response = execute(method); 

	 

	 if (response.getStatusLine().getStatusCode() == 200) {

	 entity = response.getEntity();

	 jsonResponse = new InputStreamReader(entity.getContent(), "UTF-8");

	 

	 JSONParser parser = new JSONParser();

	 

	 JSONObject obj = (JSONObject) parser.parse(jsonResponse);

	 

	 if (obj.get(ERROR_JSON_FIELD) == null) {

	 

	 // Request is successful - we save the nonce value and initiate the long-poll handling thread

	 

	 m_nonce = (String) obj.get(RTC4WEB_NONCE_JSON_FIELD);

	 m_sessionId = sessionIdentifier;

	 

	 Thread longPollThread = new Thread(this);

	 longPollThread.start();

	 


Once this request has been made and the nonce retrieved, we can start emitting the long-poll requests themselves (see listing 3). Because they are made continuously, and independent from the other requests to the Proxy Server, a separate thread is started whose role is to run the long-poll requests, retrieve their content (if any), and continuously restart them when they terminate.

The nonce must be set as an HTTP header named “rtc4web-nonce” in all long-poll requests. When content arrives, an object implementing a listener interface (the ProxyLongPollListener interface, in our code) will be notified and passed to the JSON object.

Listing 3. Running the long poll

	 // Creating the long poll HTTP request and executing it

	 

	 HttpGet pollingMethod = new HttpGet(LONG_POLL_REQUEST_URI); 

	 pollingMethod.setHeader(RTC4WEB_NONCE_HEADER, m_nonce);

	 

	 try {

	 response = execute(pollingMethod);

	 entity = response.getEntity();

	 jsonResponse = new InputStreamReader(entity.getContent(), "UTF-8");

	 

	 JSONParser parser = new JSONParser();

	 JSONObject obj = (JSONObject) parser.parse(jsonResponse);

	 

	 // Notifying the long poll listener 

	 

	 m_listener.incomingData(obj);

	 

Terminating the long poll and logging out


When your application needs to disconnect from the Proxy Server, it must close the long poll before logging out. Closing the long poll is a two-step process in which a request is first made to suspend the long poll and then a second one to terminate it.

As shown in listing 4, to suspend the long poll, an HTTP PUT request is made to the /stwebapi/RTCServlet//endUpdate URI (where is replaced by the session ID obtained from the log-in). This causes the currently running long-poll request to return (without any data).

Because we have notified the server that we want to suspend the long poll, the long-poll connection should not be re-established. In our code sample, we simply terminate the thread that was repeatedly making the long-poll connections.

Listing 4. Suspending the long poll

	 // Creating and executing the long poll suspension HTTP request

	 

	 HttpPut method = new HttpPut(MessageFormat.format(LONG_POLL_STOP_REQUEST_URI, new Object[] { m_sessionId }));

	 method.setHeader(RTC4WEB_NONCE_HEADER, m_nonce);

	 

	 try {

	 synchronized (this) {

	 m_isStarted = false;

	 }

	 

	 response = execute(method); 

	 


Once the long poll is suspended, it must be properly terminated so that the server can release resources associated with this user session. As shown in listing 5, we do this by making an HTTP DELETE request to the /stwebapi/RTCServlet/<session-id>/user URL (where <session-id> is replaced by the session ID obtained from the log-in).

Listing 5. Terminating the long poll

	 // Creating and executing the long poll termination request

	 

	 HttpDelete method = new HttpDelete(MessageFormat.format(LONG_POLL_TERMINATE_REQUEST_URI, new Object[] { m_sessionId }));

	 method.setHeader(RTC4WEB_NONCE_HEADER, m_nonce);

	 

	 try {

	 response = execute(method); 

	 


Finally, once the long poll is terminated, the application can log out by using the Logout REST API, whose URI is “stwebapi/user/connect”, method is DELETE, and which doesn't take any parameter (see listing 6).

Listing 6. Logging out

	 public JSONObject logout() throws IOException, SametimeProxyClientException {

	 

	 m_longPollHandler .stop();

	 m_longPollHandler .terminate();

	 

	 HttpDelete method = new HttpDelete(LOGIN_REQUEST_URI);

	 return executeProxyRestMethodAndRelease(method);

	 }

	 


Our application can now log in to the Proxy Server, receive asynchronous updates from the server, and then log out.

Making changes and receiving updates


In this section we show how a Java application logged into the Sametime Proxy Server can make changes (such as changing the logged-in-user presence status or status message) and react to the asynchronous updates it receives via the long-poll connection (such as the other users' presence status updates).

Changing the user presence status & status message


We change the user presence status and message, like everything else in the Proxy Server, by invoking the appropriate REST API. In this case, the API URI is "/stwebapi/user/status", the HTTP method is POST, and the accepted parameters are listed in table 2.

Table 2. SetStatus REST API parameters

 

    Name
    Type
    Description
    status
    Integer
    Optional.
    The presence status. 1=Available, 2=Away, etc ... – see the SDK documentation for more possible values.
    statusMessage
    String
    Optional.
    The status message as a String

Code listing 7 shows how to invoke this REST API to change the status, the status message, or both. The important point to remember is that the “rtc4web-nonce” HTTP header must be set, and that its value must be the nonce value received when initiating the long poll. In our sample code, a dedicated method is provided that sets the header and executes the HTTP request.

Listing 7. Setting the user presence status and status message


	 public JSONObject setStatus(UserStatus status, String statusMessage) throws IOException, SametimeProxyClientException {

	 

	 // Filling the parameter list

	 

	 List<NameValuePair> params = new ArrayList<NameValuePair>();

	 if (status != null)

	 params.add(new BasicNameValuePair(SETSTATUS_STATUS_PARAM, status.toString()));

	 if (statusMessage != null)

	 params.add(new BasicNameValuePair(SETSTATUS_STATUSMESSAGE_PARAM, statusMessage));

	 

	 UrlEncodedFormEntity entity = new UrlEncodedFormEntity(params, "UTF-8");

	 

	 // Creating the HTTP POST request

	 

	 HttpPost method = new HttpPost(SETSTATUS_REQUEST_URI);

	 method.setEntity(entity);

	 

	 // Executing the request - the executeProxyRestMethodAndRelease() method will set the rtc4web-nonce header

	 

	 return executeProxyRestMethodAndRelease(method); 

	 }

	 

Using the sample application provided with this article, you can execute this code by following these steps:

    1. Start the application with the following command line parameters in this order: the Proxy Server host name, the Proxy Server port number, the user login, and the user password.
    2. Wait for the application to start, log in, and establish the long poll.
    3. When the prompt appears, type setStatus 5 “I am in a meeting”.
    4. The logged-in-user presence status should be set to “In a Meeting”, and its status message should be “I am in a meeting”.
    5. When you're done, type “quit” to terminate the application.

Receiving status update from other users


Now that we have shown how to change the logged-in-user status, we demonstrate how to receive other users' presence status update.

This is a two step process, wherein the user whose updates are to be received must first be added to the “watch list”, allowing the client to register its “interest” in receiving updates for this user. To add the user to the watch list, a HTTP POST request must be made to the “/stwebapi/presence” URI, with the parameters listed in table 3.

Table 3. UpdateWatchList REST API parameters

 

    Name
    Type
    Description
    operation
    String
    “add” or “remove”
    users
    List
    Optional.
    A list of users separated by ';' to add to the watch list
    groupId
    String
    Optional.
    A public group id to add to the watch list.
    buddyList
    Boolean
    Optional.
    Should the whole buddy list be added to the watch list

This REST API invocation is implemented in the updateWatchList() method of the SametimeProxyClient class. You can invoke it from the provided sample application prompt to add a user to the watch list by typing updateWatchList add <user> null false (replacing <user> with a user id such as an email address).

When the user has been successfully added to the watch list, the server sends an asynchronous update to notify the application (see listing 8).

Listing 8. JSON notification for addition to watch list


	 {

	 key: 

	 sid: 6da5f78c-60d2-430c-b0ad-0c485d1d86fb

	 time: 1330557454663

	 cn: 6da5f78c-60d2-430c-b0ad-0c485d1d86fb

	 type: channel

	 value: {

	 returnCode: 200

	 displayName: Freddie Mercury

	 userId: CN=Freddie Mercury,CN=Users,DC=stoidub10,DC=com

	 action: [

	 watchlist

	 addUser

	 ]

	 resolvedName: fmercury@stoidub10.com

	 }

	 op: add

	 }

	 

All asynchronous updates follow the same format: An update array of objects, each of them containing a value object, which in turn contains a two-string array under the action key and other data. The action array indicates the type of updates that has been received, and the other data is information relevant to this update. Table 4 lists a few possible updates and their associated action array values.

Table 4. Some action array values and their meaning

 

    String 1
    String 2
    Description
    watchlist
    addUser
    User successfully added to watch list
    watchlist
    watchlist
    Watchlist user update (status, message, attribute, etc ...)
    chat
    chatReceived
    A chat request was received
    chat
    isTyping
    The chat partner started / stopped typing
    chat
    msgReceived
    A chat message has arrived
    chat
    closed
    The chat partner closed the chat window
    nway
    invitation
    A multi-user chat invitation was received

In this case, the action array contains the value “watchlist” and “addUser,” indicating a user was added to the watchlist. The resolvedName value contains the id that was passed to the update watch list REST API (allowing us to link that invocation to this asynchronous update), and the userId value contains the Sametime ID of the user who was added. This value is useful as further asynchronous updates will use it to identify the user to whom they apply.

When the user who was added to the watch list presence status changes, another update will be sent (see listing 9). This update action array contains the values “watchlist” and “watchlist,” indicating a watchlist user update. The accompanying “watchlist” object contains the user Sametime ID, his new status (5 for “in a meeting”) and his status message. By parsing this data packet, the application is notified of the status update of the user and can react accordingly.

Listing 9. JSON notification for user presence status update


	 {

	 key: 

	 sid: 5759f61b-d992-4747-a540-e84b46adad54

	 time: 1330558853020

	 cn: 5759f61b-d992-4747-a540-e84b46adad54

	 type: channel

	 value: {

	 watchlist: [

	 {

	 id: CN=Freddie Mercury,CN=Users,DC=stoidub10,DC=com

	 statusMessage: I am in a meeting 

	 status: 5

	 }

	 ]

	 action: [

	 watchlist

	 watchlist

	 ]

	 }

	 op: add

	 }

	 

Conclusion


In this article we have introduced the Sametime Proxy Server and its model for interacting with client applications. We showed how a Java application can be written to log in, receive asynchronous updates, and log out from the Proxy Server. Finally, we demonstrated how this code could be leveraged to perform Sametime actions, such as changing the user status, and receive notifications for other Sametime users.

Resources

  • IBM Sametime product page.
  • IBM Sametime Proxy Server page on the Sametime wiki.
  • IBM Sametime Software Developer's Kit contains the Proxy Server REST API documentation.
  • REST page on Wikipedia contains information about the REST architecture.
  • Comet page on Wikipedia contains information about the Comet programming technique.

About the author



Olivier Bernin is a Software Architect based at IBM's Dublin, Ireland, Software Lab. He is currently in charge of the Microsoft Office Integration and Proxy Server components of the IBM Sametime product. Prior to this assignment, Olivier was involved in the development of Sametime Advanced. You can contact him at obernin@ie.ibm.com.

  • Actions Show Menu▼


expanded Attachments (1)
collapsed Attachments (1)
Edit the article to add or modify attachments.
File TypeSizeFile NameCreated OnDelete file
application/x-zip 13 KB STProxyClient.zip 3/14/12, 10:44 PM
expanded Versions (7)
collapsed Versions (7)
Version Comparison     
VersionDateChanged by              Summary of changes
This version (7)Nov 1, 2012, 6:52:05 PM~Denise Ekresaplopoden  Fixed SDK Link
6Jul 30, 2012, 1:02:57 PM~Howard Preponemanikle  
5Mar 21, 2012, 10:14:29 PM~Elizabeth Kifreeski  Added a link to the attached source code inside the article
4Mar 14, 2012, 10:45:33 PM~Phil Xanveluvitchoopsi  
2Mar 14, 2012, 10:38:17 PM~Phil Xanveluvitchoopsi  
1Mar 14, 2012, 10:33:54 PM~Phil Xanveluvitchoopsi  
1Mar 14, 2012, 10:14:39 PM~John Bubluverjip  
expanded Comments (0)
collapsed Comments (0)
Copy and paste this wiki markup to link to this article from another article in this wiki.
Go ElsewhereStay ConnectedAbout
  • HCL Software
  • HCL Digital Solutions community
  • HCL Software Support
  • BlogsDigital Solutions blog
  • Community LinkHCL Software forums and blogs
  • About HCL Software
  • Privacy
  • Accessibility